
package com.flower.enjoyment.flower.controller;

import com.alibaba.fastjson.JSONObject;
import com.flower.enjoyment.flower.base.ResultMsg;
import com.flower.enjoyment.flower.base.WeChatConfig;
import com.flower.enjoyment.flower.config.WxParam;
import com.flower.enjoyment.flower.entity.FlowerCardOrder;
import com.flower.enjoyment.flower.entity.OrderInfo;
import com.flower.enjoyment.flower.entityDo.*;
import com.flower.enjoyment.flower.enumUtils.ResultEnum;
import com.flower.enjoyment.flower.service.*;
import com.flower.enjoyment.flower.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.http.NameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/orderApi")
@Api(value = "订单信息",description = "订单信息")
public class OrderController {
    protected static final Logger logger = LoggerFactory.getLogger(OrderController.class);
    @Autowired
    private  UserInfoService userService;
    @Autowired
    private FlowersCardOrderService flowersCardOrderService;
    @Autowired
    private ShopService shopService;
    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private PresentDetailService presentDetailService;
    @Autowired
    private FlowerCardService flowerCardService;


    @ApiOperation(value="花享卡预下单", notes="花享卡预下单")
    @ResponseBody
    @PostMapping("/weChatCardPayOrder")
    public ResultMsg weChatPayOrder(@RequestBody PayDo payDo,HttpServletRequest request){


        logger.info("选择支付类型ID====> " + payDo.getPayId()+" 卡ID====> "+payDo.getCardId()+"  用户ID"+payDo.getUserId());
        logger.info("花享卡入参：{}",JSONObject.toJSONString(payDo));


            try {

                FlowerCardOrder cardOrder = new FlowerCardOrder();
                cardOrder.setId(RandomUtil.getUuid());
                cardOrder.setCardId(payDo.getCardId());
                cardOrder.setStatus(0);
                cardOrder.setUserId(payDo.getUserId());
                cardOrder.setNo(RandomUtil.createOrderId());
                cardOrder.setLatestPayTime(DateUtil.calculateMin(new Date(), 30));
                flowersCardOrderService.insertCardOrder(cardOrder, payDo.getPayId());

                FlowerCardOrder orderEntity = flowersCardOrderService.selectCardOrderInfo(cardOrder.getId());

                WxParam wxParam = new WxParam();
                wxParam.setWxParam(wxParam, orderEntity.getNo(), "花享卡订单服务", orderEntity.getAmount(), request, WeChatConfig.CARD_NOTIFY_URL, payDo.getOpenId());
                Map<String, String> wxParamTOMap = BeanUtil.convertBeanToMap(wxParam);
                String sign = Signature.getSign(wxParamTOMap, WeChatConfig.WX_LOGIN_SECRET);
                wxParamTOMap.put("sign", sign);
                logger.info("微信小程序支付请求的Map===>" + wxParamTOMap);
                String xmlResponse = WxPayHttp.doPostPayUnifiedOrder(WeChatConfig.UNIFIED_ORDER_URL, XmlUtil.createRequestXml(wxParamTOMap));
                Map<String, String> wxParamVO = parseXmlResponse(xmlResponse);
                return new ResultMsg(ResultEnum.SUCCESS_CODE.getCode(), wxParamVO);

            } catch (Exception e) {
                e.printStackTrace();
                logger.error("花享卡下单出现异常：", e);
                return new ResultMsg(ResultEnum.ERROR_CODE.getCode(), null);
            }
    }

    @ApiOperation(value="微信支付回调", notes="微信支付回调")
    @ResponseBody
    @RequestMapping("/weChatCardNotifyResult")
    public void weChatNotifyResult (HttpServletRequest request, HttpServletResponse response){
        logger.info("微信回调request===>"+request);
        //获取微信异步通知的数据
        Map<String, String> paramsToMap = XmlUtil.reqParamsToMap(request);
        logger.info("微信回调参数map===>"+paramsToMap);
        try {
            if ("SUCCESS".equals(paramsToMap.get("return_code"))) {
                //校验微信的sign值
                boolean flag = Signature.validateSign(paramsToMap, WeChatConfig.WX_LOGIN_SECRET);
                if (flag) {
                    FlowerCardOrder orderEntity = flowersCardOrderService.selectCardOrderByNo(paramsToMap.get("out_trade_no"));
                    logger.info("微信回调订单实体===>" + orderEntity);
                    //判断是否是未支付状态
                    if (orderEntity.getStatus() == 0) {
                        //更新订单状态
                        orderEntity.setStatus(1);
                        orderEntity.setUpdateTime(new Date());
                        orderEntity.setPayNo(paramsToMap.get("transaction_id"));
                        orderEntity.setWeixinInfo(JSONObject.toJSONString(paramsToMap));
                        flowersCardOrderService.updateCardOrder(orderEntity);

                        //如果订单修改成功,通知微信接口不要在回调这个接口
                        WxPayHttp.responseXmlSuccess(response);
                    }
                }
            }else {
                throw new Exception("微信支付回调失败：" + paramsToMap.get("return_msg"));
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error("花享卡回调失败：",e);
        }

    }
    @ApiOperation(value="服务预下单", notes="服务预下单")
    @ResponseBody
    @PostMapping(value = "/weChatServicePayOrder")
    public ResultMsg weChatServicePayOrder(@RequestBody PayDo payDo, HttpServletRequest request){
  // public ResultMsg weChatServicePayOrder(PayDo payDo, HttpServletRequest request){
        logger.info("服务预下单：{}",JSONObject.toJSONString(payDo));
        logger.info("选择支付类型ID====> " + payDo.getPayType()+" 商铺ID====> "+payDo.getShopId()+"  用户ID"+payDo.getUserId());

        try {
            ShopInfoDo shopInfoDo = shopService.selectByPrimaryKey(payDo.getShopId());
            if (shopInfoDo==null){
                throw new Exception("商铺为空");
            }

            OrderInfo orderInfo = new OrderInfo();
            orderInfo.setId(RandomUtil.getUuid());
            orderInfo.setOrderNo(RandomUtil.createOrderId());
            orderInfo.setCreateTime(new Date());
            orderInfo.setTotalAmount(payDo.getAmount());
            orderInfo.setUserId(payDo.getUserId());
            orderInfo.setShopId(payDo.getShopId());
            orderInfo.setDiscountAmount(0.0);
            orderInfo.setStatus(0);
            orderInfo.setLatestPayTime(DateUtil.calculateMin(new Date(),30));
            //如果支付类型是花享卡并且花享卡享受折扣
            if (payDo.getPayType() .equals("1")){
                if (shopInfoDo.getIsCardDiscount() == 1 ){
                    orderInfo.setDiscountAmount(shopInfoDo.getCardDiscount()*orderInfo.getTotalAmount());
                    orderInfo.setDiscount(shopInfoDo.getCardDiscount());
                }else{
                    orderInfo.setDiscountAmount(0.0);
                    orderInfo.setDiscount(0.0);
                }
                //设置需要支付金额
                orderInfo.setActualAmount(orderInfo.getTotalAmount()-orderInfo.getDiscountAmount());
                orderInfo.setServiceName(payDo.getServiceName());
                UserInfoDo userInfoDo = userService.selectById(payDo.getUserId());
                if (userInfoDo==null){
                    ResultMsg resultMsg = new ResultMsg();
                    resultMsg.setCode(1001);
                    resultMsg.setMsg("用户信息获取失败");
                    return  resultMsg;
                }
                if (orderInfo.getActualAmount() > userInfoDo.getAmount()+userInfoDo.getGiveAmount()){
                    ResultMsg resultMsg = new ResultMsg();
                    resultMsg.setCode(1001);
                    resultMsg.setMsg("所剩余额不足订单金额");
                    return  resultMsg;
                }
               FlowerCardDo flowerCard = flowerCardService.selectByPrimaryKey(payDo.getCardId());
                if (flowerCard == null){
                    ResultMsg resultMsg = new ResultMsg();
                    resultMsg.setCode(1001);
                    resultMsg.setMsg("未获取到卡信息");
                    return  resultMsg;
                }
                PresentDetailDo presentDetailDo = presentDetailService.selectPresentDetailByCardId(payDo.getCardId());
                if (presentDetailDo == null){
                    ResultMsg resultMsg = new ResultMsg();
                    resultMsg.setCode(1001);
                    resultMsg.setMsg("为获取到卡片余额信息");
                    return  resultMsg;
                }

               userService.updateUserOrderInfo(userInfoDo,orderInfo,presentDetailDo);
                logger.info("卡支付返回：{}",JSONObject.toJSONString(orderInfo));
                return new ResultMsg(ResultEnum.SUCCESS_CODE.getCode(), orderInfo);
            }else{
                //选择微信支付
                if (shopInfoDo.getIsdiscount() == 1 && payDo.getAmount()>1){
                    DecimalFormat df = new DecimalFormat("###################.00");
                    orderInfo.setDiscountAmount(payDo.getAmount()-(shopInfoDo.getDiscount()*0.1*payDo.getAmount()));
                    orderInfo.setDiscount(shopInfoDo.getDiscount());
                }
            }
            //设置需要支付金额
           // if (orderInfo.getDiscountAmount() !=null && orderInfo.getDiscountAmount()>0) {
                orderInfo.setActualAmount(orderInfo.getTotalAmount() - orderInfo.getDiscountAmount());
            /*}else {
                orderInfo.setActualAmount(orderInfo.getTotalAmount());
            }*/
            orderInfo.setServiceName(payDo.getServiceName());

            logger.info("服务下单订单信息：{}",JSONObject.toJSONString(orderInfo));
            orderInfoService.insertOrderInfo(orderInfo);




            //组装参数，用户生成统一下单接口的签名
           /* List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
            packageParams.add(new BasicNameValuePair("appid", WeChatConfig.WX_LOGIN_APPID));
            packageParams.add(new BasicNameValuePair("mch_id", WeChatConfig.MCH_ID));
            packageParams.add(new BasicNameValuePair("nonce_str", RandomUtil.getUuid()));
            packageParams.add(new BasicNameValuePair("body", "服务订单"));
            packageParams.add(new BasicNameValuePair("out_trade_no",  orderInfo.getOrderNo()));//商户订单号,自己的订单ID
            packageParams.add(new BasicNameValuePair("total_fee", 100 + ""));//支付金额，这边需要转成字符串类型，否则后面的签名会失败
           // packageParams.add(new BasicNameValuePair("spbill_create_ip", IpAddress.getIpAddress(request)));
            packageParams.add(new BasicNameValuePair("notify_url", WeChatConfig.SERVICE_NOTIFY_URL));//支付成功后的回调地址
            packageParams.add(new BasicNameValuePair("trade_type", "JSAPI"));//支付方式
            packageParams.add(new BasicNameValuePair("openid", payDo.getOpenId()));//用户的openID，自己获取
            Collections.sort(packageParams, new Comparator<NameValuePair>() {
                @Override
                public int compare(NameValuePair arg0, NameValuePair arg1) {
                    return arg0.getName().compareTo(arg1.getName());
                }
            });

            String sign = genPackageSignForWxPay(packageParams, WxSPConfig.MCH_KEY);

            packageParams.add(new BasicNameValuePair("sign", sign));
*/


            WxParam wxParam = new WxParam();
            wxParam.setWxParam(wxParam, orderInfo.getOrderNo(),"服务订单",orderInfo.getActualAmount(), request, WeChatConfig.SERVICE_NOTIFY_URL, payDo.getOpenId());
            Map<String, String> wxParamTOMap = BeanUtil.convertBeanToMap(wxParam);
            String sign = Signature.getSign(wxParamTOMap, WeChatConfig.WX_LOGIN_SECRET);
            wxParamTOMap.put("sign", sign);
            logger.info("微信小程序支付服务请求的Map===>" + wxParamTOMap);


            //String xmlResponse = WxPayHttp.doPostPayUnifiedOrder(WxSPConfig.UNIFIED_ORDER_URL, toXml(packageParams));
            String xmlResponse = WxPayHttp.doPostPayUnifiedOrder(WeChatConfig.UNIFIED_ORDER_URL, XmlUtil.createRequestXml(wxParamTOMap));
            Map<String, String> wxParamVO = parseXmlResponse(xmlResponse);
            logger.info("返回预下单信息：{}",JSONObject.toJSONString(wxParamVO));
            return new ResultMsg(ResultEnum.SUCCESS_CODE.getCode(), wxParamVO);

        }catch (Exception e){
            e.printStackTrace();
            logger.error("服务订单下单出现异常：",e);
            return new ResultMsg(ResultEnum.ERROR_CODE.getCode(),null);
        }
    }

    public static String genPackageSignForWxPay(List<NameValuePair> params, String apiKey) throws Exception {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(apiKey);
        logger.debug("连接商户key:"+sb.toString());
        String packageSign = getMessageDigest(sb.toString().getBytes("utf-8")).toUpperCase();
        logger.debug("md5编码并转成大写："+packageSign);
        return packageSign;
    }
    public static String getMessageDigest(byte[] buffer) {
        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(buffer);
            byte[] md = mdTemp.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }
    public static String toXml(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        for (int i = 0; i < params.size(); i++) {
            sb.append("<" + params.get(i).getName() + ">");

            sb.append("<![CDATA[" + params.get(i).getValue() + "]]>");

            sb.append("</" + params.get(i).getName() + ">");
        }
        sb.append("</xml>");
        logger.info("微信支付XML格式数据：{}",sb.toString());
        return sb.toString();
    }
    @ApiOperation(value="微信支付服务订单回调", notes="微信支付服务订单回调")
    @ResponseBody
    @RequestMapping("/weChatServiceNotifyResult")
    public void weChatServiceNotifyResult (HttpServletRequest request, HttpServletResponse response){
        logger.info("微信服务订单回调request===>"+request);
        //获取微信异步通知的数据
        Map<String, String> paramsToMap = XmlUtil.reqParamsToMap(request);
        logger.info("微信服务订单回调参数map===>"+paramsToMap);
        try {
            //校验微信的sign值
            boolean flag = Signature.validateSign(paramsToMap, WeChatConfig.WX_LOGIN_SECRET);
            if (flag) {
                OrderInfoDo orderEntity = orderInfoService.selectByOrderNo(paramsToMap.get("out_trade_no"));
                logger.info("微信回调服务订单实体===>" + orderEntity);
                //判断是否是未支付状态
                if (orderEntity.getStatus() == 0) {
                    OrderInfo orderInfo = new OrderInfo();
                    //更新订单状态
                    orderInfo.setStatus(1);
                    orderInfo.setPayTime(new Date());
                    orderInfo.setPayType(1);
                    orderInfo.setUpdateTime(new Date());
                    orderInfo.setPayNo(paramsToMap.get("transaction_id"));
                    orderInfo.setWeixinInfo(JSONObject.toJSONString(paramsToMap));
                    orderInfo.setShopId(orderEntity.getShopId());
                    orderInfo.setActualAmount(orderEntity.getActualAmount());
                    orderInfo.setId(orderEntity.getId());
                    orderInfoService.updateOrderInfo(orderInfo);

                    //如果订单修改成功,通知微信接口不要在回调这个接口
                    WxPayHttp.responseXmlSuccess(response);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error("服务订单回调失败：",e);
        }

    }

    /*解析微信请求响应的数据并返回小程序需要的数据*/

    private  Map<String,String> parseXmlResponse(String xmlResponse){
        Map<String,String> resultMap=new HashMap<>();
        //判断sign值是否正确
        Boolean flag = Signature.validateResponseXmlToMap(xmlResponse);
        if(flag){
            Map<String, String> map = XmlUtil.xmlToMap(xmlResponse);
            logger.info("微信支付请求响应的数据的预支付ID====>"+map.get("prepay_id"));
            resultMap.put("appId",WeChatConfig.WX_LOGIN_APPID);
            resultMap.put("timeStamp",String.valueOf(DateUtil.strToTime(DateUtil.format(new Date()))));
            resultMap.put("nonceStr",RandomUtil.getUuid());
            resultMap.put("package","prepay_id="+map.get("prepay_id"));
            resultMap.put("signType","MD5");
            String sign = Signature.getSign(resultMap, WeChatConfig.WX_LOGIN_SECRET);
            resultMap.put("paySign",sign);

        }
        return resultMap;
    }

}

